import { reactive, ref, computed, Ref } from "vue";
import { TableProps, MessagePlugin } from 'tdesign-vue-next';
import { TableLocalConfig, DefalutData, EmptyEnum } from "./type.d";
import { FormType } from '@/view/compont/crud/component/formDialog/type.d'
import type EmitsDefination from "./extends/emits";

export default class <T extends object> {
  /**
   * 数据源
   */
  public data = ref<T[]>([])

  /**
   * 分页
   */
  public pagination = reactive<TableProps['pagination']>({
    defaultCurrent: 1,
    defaultPageSize: 5,
    total: 0,
  })

  /**
   * 选中列
   */
  public selectedRowKeys = ref<TableProps['selectedRowKeys']>([])

  /**
   * 排序设置
   */
  public sort = ref<TableProps['sort']>([]);

  /**
   * 导出按钮禁用
   */
  public exportDisabled = computed(() => this.selectedRowKeys.value.length === 0)

  /**
   * 弹窗开关
   */
  public dialogVisible = ref<boolean>(false);

  /**
   * 表单数据
   */
  public formData = reactive<DefalutData<T>>({} as DefalutData<T>)
  private defaultFormData: DefalutData<T>

  /**
   * 表单类型
   */
  public formType = ref<FormType>(FormType.Info)

  /**
   * 弹窗标题
   */
  public dialogTitle = ref('')

  /**
   * 组件事件
   */
  private emits: EmitsDefination;

  /**
   * 提交按钮loading
   */
  public sumbitLoading = ref<boolean>(false);

  /**
   * 表格loading
   */
  public tableLoading = ref<boolean>(false);

  /**
   * 查询返回的状态
   * 用来控制空状态的显示
   */
  public queryStatus = ref<EmptyEnum>(EmptyEnum[200]);

  /**
   * ⭐⭐ 初始化 ⭐⭐
   */
  constructor(tableName: string, defalutData: DefalutData<T>, emits: EmitsDefination) {
    this.emits = emits;

    // 初始化表格配置
    const tableLocalConfig = reactive<TableLocalConfig>(this.getTableLocalConfig(tableName))
    this.sort.value = tableLocalConfig?.sort || []
    
    // 初始化表单数据
    this.defaultFormData = JSON.parse(JSON.stringify(defalutData))
    Object.assign(this.formData, defalutData)
    
    // 获取表单数据
    this.getList();
  }

  /**
   * 获取表格本地配置
   */
  public getTableLocalConfig = (tableName: string):TableLocalConfig => {
    const tableCon = localStorage.getItem(tableName) || '{}'
    return JSON.parse(tableCon)
  }

  /**
   * 获取列表
   */
  public getList = () => {
    this.tableLoading.value = true
    this.emits('getList', (list: Array<T>, total: number) => {
      this.data.value = list
      this.tableLoading.value = false
      this.pagination.total = total
    }, (code: EmptyEnum) => {
      this.queryStatus.value = code
      this.tableLoading.value = false
    })
  }

  /**
   * 新增按钮点击
   */
  public addBtnClick = () => {
    this.dialogVisible.value = true
    this.formType.value = FormType.Add
    Object.assign(this.formData[FormType.Add], this.defaultFormData[FormType.Add])
  }

  /**
   * 编辑按钮点击
   * @param row 当前行
   */
  public editBtnClick = (row: T) => {
    this.dialogVisible.value = true
    this.formType.value = FormType.Edit
    this.defaultFormData[FormType.Edit] = JSON.parse(JSON.stringify(row))
    Object.assign(this.formData[FormType.Edit], row)
  }

  /**
   * 详情按钮点击
   * @param row 当前行
   */
  public infoBtnClick = (row: T) => {
    this.dialogVisible.value = true
    this.formType.value = FormType.Info
    Object.assign(this.formData[FormType.Info], row)
  }

  /**
   * 提交表单数据
   */
  public onSumbit = () => {
    this.sumbitLoading.value = true

    const closeDialog = (msg: string) => {
      this.dialogVisible.value = false
      this.sumbitLoading.value = false
      MessagePlugin.success(msg)
    }

    if(this.formType.value === FormType.Edit) {
      this.emits(
        'updateData', 
        this.formData[FormType.Edit] as object, 
        () => {
          closeDialog('修改成功')
        },
        (msg) => {
          MessagePlugin.error(msg)
          this.sumbitLoading.value = false
        }
      )
    }
  }

  /**
   * 重置表单数据
   */
  public onReset = () => {
    Object.assign(this.formData[this.formType.value], this.defaultFormData[this.formType.value])
    MessagePlugin.success('重置成功')
  }

  /**
   * 选择项改变
   * @param value 所选择的下标数组
   * @param ctx 选择内容封装
   */
  public rehandleSelectChange: TableProps['onSelectChange'] = (value, ctx) => {
    this.selectedRowKeys.value = value;
  }

  /**
   * 排序改变时触发
   * @param val 排序对象
   */
  public sortChange: TableProps['onSortChange'] = (val) => {
    this.sort.value = val;
  };
}
